﻿using System;
using System.Net;
using System.Net.Sockets;

namespace ScreenServer
{
    public class MulticastServer
    {
        private ushort _seq;
        private readonly byte[] _buffer;
        private readonly Socket _socket;
        public IPAddress Group { get; private set; }
        public int Port { get; private set; }
        public int TTL { get; private set; }

        public MulticastServer(IPAddress group, int port, int ttl)
        {
            Group = group;
            Port = port;
            TTL = ttl;
            _socket =
                new Socket(
                    AddressFamily.InterNetwork,
                    SocketType.Dgram,
                    ProtocolType.Udp);
            _socket.SetSocketOption(
                SocketOptionLevel.IP,
                SocketOptionName.AddMembership,
                new MulticastOption(Group));
            _socket.SetSocketOption(
                SocketOptionLevel.IP,
                SocketOptionName.MulticastTimeToLive,
                TTL);
            _buffer = new byte[1024+32];
            new byte[] {0x09,0x33,0x00,0x34,0x52,0x10}.CopyTo(_buffer, 0);
        }
        public void Start()
        {
            var endPoint = new IPEndPoint(Group, Port);
            _socket.Connect(endPoint);
        }
        public void Send(byte[] buffer, int offset, int length)
        {
            //MagicValue, seq, TotalLength, TotalPacket, PacketNum, Reserved
            //6,2,4,4,4,12
            var totalPacket = (length >> 10) + ((length & 0x3FF) > 0 ? 1 : 0);
            _seq++;
            BitConverter.GetBytes(_seq).CopyTo(_buffer, 6);
            BitConverter.GetBytes(length).CopyTo(_buffer, 8);
            BitConverter.GetBytes(totalPacket).CopyTo(_buffer, 12);
            var packetNum = 0;
            for (var sent = 0; sent < length;)
            {
                var len = (sent + 1024 > length) ? length - sent : 1024;
                BitConverter.GetBytes(packetNum).CopyTo(_buffer, 16);
                Buffer.BlockCopy(buffer, offset+sent, _buffer, 32, len);
                _socket.Send(_buffer, 0, len+32, SocketFlags.None);
                sent += len;
                packetNum++;
                //Console.WriteLine("\t"+sent);
            }
        }
        public void Stop()
        {
            try
            {
                _socket.Close();
            }
            catch (Exception)
            {
            }
        }
    }
}